'use strict';

const redis = require('redis');
const expModel = require('./dbutility').expModel;
const cabModel = require('./dbutility').cabModel;
const gpUtility = require('./gputility');
const constant = require('./constant');
const logger = require('./logutility').logger('rdsutility');
const client = redis.createClient();

client.on('error', function(error) {
    logger.error(error);
});

initReTelNamesHSet();
initCabPwdInUseSet();

/**
 * 执行电话号码哈希表的初始化
 * 
 * @param {Function}cb 回调函数
 */
function initReTelNamesHSet(cb) {
    gpUtility.excuteGP(initReTelNamesHSetGP(cb));
}

/**
 * 电话号码哈希表的初始化
 * 
 * @param {Function}cb 回调函数
 */
function* initReTelNamesHSetGP(cb) {
    try {
        let exps = yield expModel.getExpAll();
        let expsObj = {};
        for (let exp of exps) {
            let tel4 = constant.TEL4_STR + exp.expReTel.slice(-4);
            if (!(tel4 in expsObj)) {
                expsObj[tel4] = {};
            }
            expsObj[tel4][exp.expReTel] = exp.expReName;
        }

        for (let tel4 in expsObj) {
            yield hmsetReTelNames(tel4, expsObj[tel4]);
        }
        
        if(typeof(cb)==='function'){
            cb();
        }
        
        logger.info('电话号码哈希表初始化成功！')
    } catch (e) {
        logger.error('电话号码哈希表初始化失败！')
        logger.error(e);
    }
}

/**
 * 向Redis中添加哈希表(key：收件人电话号码后四位,field:收件人电话号码,value:收件人姓名)
 * 
 * @param {string}tel4 收件人电话号码后四位
 * @param {Object}reTelNamesObj 收件人电话号码及姓名Object{收件人电话号码：收件人姓名,...}
 * @return {Promise}
 */
function hmsetReTelNames(tel4, reTelNamesObj) {
    return new Promise((resolve, reject) => {
        client.hmset(tel4, reTelNamesObj, (err, res) => {
            if (err) {
                reject(err);
            } else {
                resolve();
            }
        });
    });
}

/**
 * 根据电话号码后四位取得相关收件人信息一览
 * 
 * @param {string}tel4 电话号码后四位
 * @return {Promise}
 */
function getReTelNames(tel4) {
    return new Promise((resolve, reject) => {
        let key = constant.TEL4_STR + tel4;
        client.hgetall(key, (err, res) => {
            if (err) {
                reject(err);
            } else {
                let reTelNames = [];
                for (let k in res) {
                    let expReTel = k;
                    let expReName = res[k];
                    reTelNames.push({ expReTel, expReName });
                }
                resolve(reTelNames)
            }
        });
    });
}

/**
 * 想电话号码哈希表中插入新的记录
 * 
 * @param {string}reTel 收件人电话号码
 * @param {string}reName 收件人姓名
 * @return {Promise}
 */
function addReTelName(reTel, reName) {
    return new Promise((resolve, reject) => {
        let key = constant.TEL4_STR + reTel.slice(-4);
        client.hset(key, reTel, reName, (err, res) => {
            if (err) {
                logger.error('电话号码哈希表插入失败！');
                logger.error({ reTel, reName });
                logger.error(err);
            }
            resolve();
        });
    });
}

/**
 * 执行快递柜取件码集合的初始化
 * 
 * @param {Function}cb 回调函数
 */
function initCabPwdInUseSet(cb) {
    gpUtility.excuteGP(initCabPwdInUseSetGP(cb));
}

/**
 * 快递柜取件码集合的初始化
 * 
 * @param {Function}cb 回调函数
 */
function* initCabPwdInUseSetGP(cb) {
    try {
        let cabs = yield cabModel.getAllCabInUse();
        if(cabs.length>0){
            let cabPwds = [];
            for (let cab of cabs) {
                cabPwds.push(cab.cabPwd);
            }
            yield smaddCabPwdInUse(cabPwds);
        }

        if(typeof(cb)==='function'){
            cb();
        }
        
        logger.info('快递柜取件码集合初始化成功！')
    } catch (e) {
        logger.error('快递柜取件码集合初始化失败！')
        logger.error(e);
    }
}

/**
 * 向快递柜取件码集合中添加快递柜取件码
 * 
 * @param {Array}cabPwds 快递柜取件码数组
 * @return {Promise}
 */
function smaddCabPwdInUse(cabPwds) {
    return new Promise((resolve, reject) => {
        client.sadd(constant.CAB_PWD_STR, cabPwds, (err, res) => {
            if (err) {
                reject(err);
            } else {
                resolve();
            }
        });
    });
}

/**
 * 判断快递柜取件码是否存在于快递柜取件码集合中
 * 
 * @param {string}cabPwd 快递柜取件码 
 * @return {Promise}
 */
function hasCabPwdInUse(cabPwd) {
    return new Promise((resolve, reject) => {
        client.sismember(constant.CAB_PWD_STR, cabPwd, (err, res) => {
            if (err) {
                reject(err);
            } else {
                resolve(res === 1)
            }
        });
    });
}

/**
 * 向快递柜取件码集合中加入新的元素
 * 
 * @param {string}cabPwd 快递柜取件码
 * @return {Promise}
 */
function addCabPwdInUse(cabPwd) {
    return new Promise((resolve, reject) => {
        client.sadd(constant.CAB_PWD_STR, cabPwd, (err, res) => {
            if (err) {
                reject(err);
            } else {
                resolve();
            }
        });
    });
}

module.exports.redisClient = client;
module.exports.initReTelNamesHSet = initReTelNamesHSet;
module.exports.getReTelNames = getReTelNames;
module.exports.addReTelName = addReTelName;
module.exports.initCabPwdInUseSet = initCabPwdInUseSet;
module.exports.hasCabPwdInUse = hasCabPwdInUse;
module.exports.addCabPwdInUse = addCabPwdInUse;